package io.github.iogogogo.scheduled.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import io.github.iogogogo.commons.exception.BizException;
import io.github.iogogogo.commons.http.OkHttpUtils;
import io.github.iogogogo.commons.util.JsonParse;
import io.github.iogogogo.scheduled.model.XxlJobGroup;
import io.github.iogogogo.scheduled.properties.XxlJobProperties;
import io.github.iogogogo.scheduled.service.JobGroupService;
import io.github.iogogogo.scheduled.service.JobLoginService;
import io.github.iogogogo.scheduled.support.XxlJobHttpConfig;
import io.github.iogogogo.scheduled.support.XxlJobResponseWrapper;
import io.vavr.Tuple3;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * Created by tao.zeng on 2024/11/19.
 */
@Slf4j
@Component
public class JobGroupServiceImpl implements JobGroupService, InitializingBean {

    @Resource
    private JobLoginService jobLoginService;

    @Resource
    private XxlJobProperties xxlJobProperties;

    private XxlJobProperties.AdminProperties admin;
    private XxlJobProperties.ExecutorProperties executor;


    @Override
    public void afterPropertiesSet() throws Exception {
        executor = xxlJobProperties.getExecutor();
        admin = xxlJobProperties.getAdmin();
    }

    @Override
    public List<XxlJobGroup> getJobGroup() {
        String url = String.join("/", admin.getAddresses(), "jobgroup/pageList");
        log.debug("xxl-job executor list url: {}", url);
        OkHttpUtils okHttpUtils = OkHttpUtils.getInstance().setOkHttpClient(XxlJobHttpConfig.getInstance().getOkHttpClient());


        int pageSize = 100;
        Map<String, Object> param = new HashMap<>();
        param.put("appname", executor.getAppname());
        param.put("title", executor.getTitle());
        param.put("start", 0);
        param.put("length", pageSize);

        Tuple3<Integer, Boolean, String> tuple3 = okHttpUtils.get(url, param, Map.of("cookie", jobLoginService.getCookie()));
        String respJson = tuple3._3;
        log.debug("xxl-job executor list respJson: {}", respJson);

        XxlJobResponseWrapper<List<XxlJobGroup>> wrapper = JsonParse.tryParse(respJson, new TypeReference<>() {
        });

        /*
        long recordsTotal = wrapper.getRecordsTotal();
        if (data.size() <= recordsTotal) {
            log.info("未获取到全部数据，开始分页获取，共 {} 页", (recordsTotal - 1) / pageSize + 1);
        }*/

        return Objects.isNull(wrapper) ? List.of() : wrapper.getData();
    }

    @Override
    public boolean autoRegisterGroup() {
        String url = String.join("/", admin.getAddresses(), "jobgroup/save");

        Integer addressType = executor.getAddressType();
        String address = executor.getAddress();

        Map<String, Object> param = new HashMap<>();
        param.put("appname", executor.getAppname());
        param.put("title", executor.getTitle());
        param.put("addressType", addressType);
        if (StringUtils.equals(String.valueOf(addressType), "1")) {
            if (StringUtils.isEmpty(address)) {
                throw new BizException("手动录入模式下,执行器地址列表不能为空");
            }
            param.put("addressList", address);
        }
        OkHttpUtils okHttpUtils = OkHttpUtils.getInstance().setOkHttpClient(XxlJobHttpConfig.getInstance().getOkHttpClient());

        Tuple3<Integer, Boolean, String> tuple3 = okHttpUtils.postForm(url, param, Map.of("cookie", jobLoginService.getCookie()));
        String respJson = tuple3._3;
        Map<String, Object> map = JsonParse.tryParse(respJson, new TypeReference<>() {
        });
        if (MapUtils.isNotEmpty(map) && StringUtils.equals(map.get("code").toString(), "200")) {
            return true;
        } else {
            throw new BizException("xxl-job executor register failure: " + respJson);
        }
    }

    @Override
    public boolean preciselyCheck() {
        List<XxlJobGroup> jobGroup = getJobGroup();
        Optional<XxlJobGroup> has = jobGroup.stream()
                .filter(x -> x.getAppname().equals(executor.getAppname()) && x.getTitle().equals(executor.getTitle()))
                .findAny();
        return has.isPresent();
    }
}
